﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace jSLCore.SyncWCFChannelGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
#if (!DEBUG)
            

            try
            {
#endif
                string path = 
//@"E:\Users\jinek\Documents\Visual Studio 2008\Проекты\jSLCore\TestSLClient\Service References\mainService\Reference.cs";
                args[0];
            var src = System.IO.File.ReadAllText(path);


            var regex = new Regex(@"public interface (?<channelClassName>(w|.)+) : (?<baseInterfaceName>(w|.)+), System.ServiceModel.IClientChannel", RegexOptions.IgnoreCase);
            var match = regex.Match(src);

            var asyncInterfaceName = match.Groups["channelClassName"].Value;
            Console.WriteLine("Канал будет генерироваться из {0}", asyncInterfaceName);

            var baseInterfaceName = match.Groups["baseInterfaceName"].Value.Split('.').Last();
            Console.WriteLine("Методы буду искаться в {0}", baseInterfaceName);

            var clIndex = src.IndexOf(" public interface " + baseInterfaceName);

            var methodsClassBody = src.Substring(clIndex);
            var endOfClass = methodsClassBody.IndexOf('}');
            methodsClassBody = methodsClassBody.Substring(0, endOfClass + 1);

            var mRegex = new Regex(@"System.IAsyncResult (?<methodName>.+)\((?<params>.+)", RegexOptions.IgnoreCase);

            Console.WriteLine("-------------------------------------");


            string res = string.Empty;

            var newClassName = asyncInterfaceName.Substring(0, asyncInterfaceName.LastIndexOf("Channel")) + "SyncedChannel";
                var nl = System.Environment.NewLine;

                var nsName = Regex.Match(src,@"namespace (?<nsName>.+)\{").Groups["nsName"].Value.Replace("{",string.Empty);

                res += @"using System.ServiceModel;
using System.ServiceModel.Channels;
namespace "+nsName+@"{
";


                res += @"public class " + newClassName + nl+"{"+nl;
            res += @"private " + asyncInterfaceName + " _asyncChannel;";
            res +=
                string.Format(nl +
                    @"#region Constructors
        public {1}(string endpointConfigurationName, EndpointAddress remoteAddress)
        {{
            var factory = new ChannelFactory<{0}>(endpointConfigurationName, remoteAddress);
            CreateChannel(factory);
        }}

        public {1}(Binding binding, EndpointAddress rem)
        {{
            var factory = new ChannelFactory<{0}>(binding, rem);
            CreateChannel(factory);
        }}

        public {1}(string endpointConfigurationName)
        {{
            var factory = new ChannelFactory<{0}>(endpointConfigurationName);
            CreateChannel(factory);
        }}

        private void CreateChannel(ChannelFactory<{0}> factory)
        {{
            _asyncChannel = factory.CreateChannel();
        }}

        #endregion


",
                    asyncInterfaceName, newClassName);
            foreach (Match matche in mRegex.Matches(methodsClassBody))
            {
                var methodName = matche.Groups["methodName"].Value.Trim();
                var parames = matche.Groups["params"].Value.Replace(@"System.AsyncCallback callback, object asyncState);", string.Empty).Trim().Trim(',');

                var shortName = methodName.Substring(5);

                var retTypeName = Regex.Match(methodsClassBody, @"(?<retTypeName>.+) End" + shortName+@"\(").Groups["retTypeName"].Value.Trim();

                Console.WriteLine(methodName);
                Console.WriteLine("Параметры: " + parames);
                Console.WriteLine("Возвращает:" + retTypeName);

                string method = "public";
                method += " " + retTypeName + " " + shortName + "(" + parames + @")
{
var result = _asyncChannel.";
                method += methodName + "(";

                var pars = parames.Split(',');
                foreach (var par in pars)
                {
                    if (par != string.Empty)
                        method += par.Split(' ').Last() + ',';
                }

                method += @"null,null);
";
                if(retTypeName!="void")
                {
                    method += "return ";
                }
                method += "_asyncChannel.End" + shortName + @"(result);
}
";

                res += method;

            }

            res += @"
}
}
";
            Console.WriteLine(res);

            Console.WriteLine("Готово");
          
                var inf = new FileInfo(path);
                var newFileName = inf.DirectoryName+@"\"+inf.Name.Replace(".cs",string.Empty) + "Synced.cs";

                var writer = new FileStream(newFileName,FileMode.Create);

                var bytes = Encoding.ASCII.GetBytes(res);

                writer.Write(bytes,0,bytes.Length);
#if (!DEBUG)
            }
      
            

      

            catch (Exception exception)
            {

                Console.WriteLine(exception);
            }
#endif

            Console.ReadLine();
        }
    }
}
